﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Linq;
using System.Configuration;
using System.Diagnostics;
using PdfCompiler.Properties;

namespace PdfCompiler
{
    public partial class MainForm : Form
    {
        //string rootFolder = Settings.Default.CarpetaOrigen;
        //string outputFolder = Settings.Default.CarpetaDestino;
        //string filter = Settings.Default.Filtro;

        FileStream logFile;
        StreamWriter logger; 
        private string[] fileNames;
        private IOrderedEnumerable<IGrouping<string, FileInfo>> despachos;

        public MainForm()
        {
            InitializeComponent();

            logFile = new FileStream("log.txt", FileMode.Create);
            logger = new StreamWriter(logFile);

            this.rootFolderBrowserDialog.SelectedPath = Settings.Default.CarpetaOrigen;
            this.outputFolderBrowserDialog.SelectedPath = Settings.Default.CarpetaDestino;

            this.txtFolder.Text = Settings.Default.CarpetaOrigen;
            this.txtOutputFolder.Text = Settings.Default.CarpetaDestino;
            this.txtFilter.Text = Settings.Default.Filtro;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                logger.Flush();
                logger.Close();
            }
            catch { }

            Application.Exit();
        }

        private void btnExaminar_Click(object sender, EventArgs e)
        {
            DialogResult result = rootFolderBrowserDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                Settings.Default.CarpetaOrigen = rootFolderBrowserDialog.SelectedPath;
                this.txtFolder.Text = Settings.Default.CarpetaOrigen;

                BuscarArchivos();
            }
        }

        private void BuscarArchivos()
        {
            if (String.IsNullOrEmpty(Settings.Default.CarpetaOrigen))
            {
                MessageBox.Show(
                    "Seleccione un directorio de orígen.",
                    "Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);

                return;
            }

            Log(String.Format("Buscado archivos en {0}...\n", Settings.Default.CarpetaOrigen));

            fileNames = Directory.GetFiles(Settings.Default.CarpetaOrigen, Settings.Default.Filtro, SearchOption.AllDirectories);
            
            IEnumerable<FileInfo> files = fileNames.Select(f => new FileInfo(f));

            foreach (var file in files)
                Log(file + "\n");

            Log(String.Format("\nSe encontraron {0} archivos dentro de {1}.\n", files.Count(), Settings.Default.CarpetaOrigen));

            Log("\nDetectando despachos...\n");

            despachos = from f in files
                        where f.Name.Remove(f.Name.ToUpper().IndexOf(".PDF")).Length >= 16
                        group f by f.Name.ToUpper().Substring(0, 16) into fileGroup
                        orderby fileGroup.Key
                        select fileGroup;

            if (despachos.Count() == 0)
                Log("No se encontraron despachos.\n");
            else
            {
                Log("Se encontraron los siguientes despachos.\n");
                foreach (var despacho in despachos)
                {
                    Log(String.Format("{0}:\n", despacho.Key));

                    if (despacho.Count() > 1)
                    {
                        var directories = from f in despacho
                                      group f by f.DirectoryName into fileGroup
                                      orderby fileGroup.Key
                                      select fileGroup;

                        foreach (var directory in directories)
                        {
                            Log(String.Format("\tDirectorio: {0}\n", directory.Key));
                            
                            if (directory.Count() > 1)
                                Log(String.Format("\t\t{0} archivos parciales encontrados.\n", directory.Count()));
                            else
                                Log(String.Format("\t\tArchivo único: {0}. Se ignorará.\n", directory.First().Name));
                        }
                    }
                    else
                        Log(String.Format("\tArchivo único: {0} en {1}. Se ignorará.\n", despacho.First().Name, despacho.First().DirectoryName));
                }
            }
        }

        private void btnCompile_Click(object sender, EventArgs e)
        {
            if (despachos == null || despachos.Count() == 0)
            {
                MessageBox.Show(
                    "No hay despachos para compilar.", 
                    "Error", 
                    MessageBoxButtons.OK, 
                    MessageBoxIcon.Exclamation);

                return;
            }

            Log("Compilando despachos...\n");
            foreach (var despacho in despachos)
            {
                Log(String.Format("> Despacho: {0}\n", despacho.Key));

                if (despacho.Count() > 1)
                {
                    var directories = from f in despacho
                                      group f by f.DirectoryName into fileGroup
                                      orderby fileGroup.Key
                                      select fileGroup;

                    foreach (var directory in directories)
                    {
                        Log(String.Format("\tDirectorio: {0}\n", directory.Key));

                        if (directory.Count() > 1)
                                CompilarArchivos(directory, despacho.Key);
                        else
                            Log(String.Format("\t\tArchivo único: {0} > No se procesará.\n", directory.First().Name));
                    }
                }
                else
                    Log(String.Format("\tArchivo único: {0} > No se procesará.\n", despacho.First().Name));
            }

            despachos = null;

            GC.Collect();

            MessageBox.Show(
                "La compilación ha concluido satisfactoriamente.",
                "Compilación Exitosa",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information);

            if (!String.IsNullOrEmpty(Settings.Default.CarpetaDestino))
            {
                Process.Start(Settings.Default.CarpetaDestino);
            }
        }

        private void CompilarArchivos(IGrouping<string, FileInfo> directory, string legajo)
        {
            try
            {
                string outfolder = Settings.Default.CarpetaDestino;

                Log(String.Format("\t\tCompilando archivos...\n"));

                if (String.IsNullOrEmpty(Settings.Default.CarpetaDestino))
                    outfolder = directory.Key;
                
                string output = Path.Combine(outfolder, legajo + ".PDF");
                if (File.Exists(output))
                {
                    Log(String.Format("\t\tEl archivo ya existe: {0}\n", output));
                }
                else
                {
                    string[] filepaths = directory.Select(d => d.FullName).ToArray();
                    PdfHelper.ConcatenatePdfFiles(filepaths, output);
                    
                    Log(String.Format("\t\tCompilación exitosa. Se generó: {0}\n", output));
                }
            }
            catch (Exception ex)
            {
                Log(String.Format("\t\tERROR: {0}\n", ex.Message));
            }
        }

        private void Log(string message)
        {
            rtbStatus.AppendText(message);
            rtbStatus.ScrollToCaret();

            logger.WriteLine(DateTime.Now.ToLocalTime() + ": " + message);
            logger.Flush();
        }

        private void btnOutput_Click(object sender, EventArgs e)
        {
            DialogResult result = outputFolderBrowserDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                Settings.Default.CarpetaDestino = outputFolderBrowserDialog.SelectedPath; ;
                this.txtOutputFolder.Text = Settings.Default.CarpetaDestino;
            }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            BuscarArchivos();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            var result = MessageBox.Show(
                "Está seguro que desea salir de la aplicación?",
                "Salir", 
                MessageBoxButtons.YesNoCancel, 
                MessageBoxIcon.Question, 
                MessageBoxDefaultButton.Button2);

            if (result == DialogResult.Yes)
            {
                Settings.Default.Save();
            }
            else
            {
                e.Cancel = true;
            }
                
        }
    }
}
